#!/usr/bin/env python2
#coding:utf8

import os
import sys
import socket
import time
import subprocess
import fcntl
import types
import errno
import errno
import getopt
import copy
import random
from utils import _get_value, Exp, _str2dict, _dwarn, _dmsg, _derror, \
        _lock_file, _exec_shell, _exec_remote2, _exec_pipe
from config import Config
from localfs import LocalFs
from storage import Storage
from movedata import Object, Replica, Node, Location, Rack
from instence import Instence
from metanode import MetaNode
from metanode_balance_with_diskmap import balance as metanode_balance


class InstenceDrop(Instence):
    def __init__(self, config, home):
        service = int(os.path.split(home)[1])
        super(InstenceDrop, self).__init__(config, service)
        self.localfs = LocalFs(self.home)
        self.storage = Storage(self.config)

        key = self.home + "/deleting"
        tmp = key + ".tmp"
        self.lock_file = _lock_file(tmp)
        cmd = "mv %s %s" % (tmp, key)
        os.system(cmd)
        self.busymeta = []

    def decrease(self):
        stat = self.show()
        if not stat['running']:
            return

        if int(stat['used']) < (1024 * 1024 * 1024 * 10):
            print("used %s, less than 10GB, exit" % (stat['used']))
            return

        lst = self.storage.list_node()
        used = 0
        capacity = 0
        #print (lst)
        for i in lst:
            s = self.storage.nodeinfo(i)
            #print (s)
            capacity += int(s['capacity'])
            used += int(s['used'])

        total_per = float(used) / float(capacity) * 100
        self_per = float(stat['used']) / float(stat['capacity']) * 100

        print ('total used %u/%u %f%%' % (used, capacity, total_per))
        print ('self used %u/%u %f%%' % (int(stat['used']), int(stat['capacity']), self_per))

        if (self_per < total_per):
            print("total %f self %f, exit" % (total_per, self_per))
            return

        lst = self.localfs.build_chunk_list("raw")['raw']
        random.shuffle(lst)

        dec = (((self_per - total_per) * 0.99) / self_per)
        needmove = int(float(len(lst)) * dec)
        _dmsg("move chunk %u total %u" % (needmove, len(lst)))
        newlst = lst[:needmove]

        time.sleep(10)

        chunklist = []
        for c in newlst:
            try:
                chkid = self.storage.chkid(c)
            except Exp, e:
                if (e.errno == errno.ENOENT):
                    continue
                else:
                    raise
            chunklist.append((chkid, self.name))

        ret = self.storage.cast_chunks(chunklist, 100, False)
        if (ret):
            raise Exp(errno.EAGAIN, "need retry")

    def skip(self, s):
        if (s == '0'):
            os.system("rm %s/skip" % (self.home))
            self.start()
        elif (s == '1'):
            os.system("touch %s/skip" % (self.home))
            self.stop()


def usage():
    print ("usage:")
    print (sys.argv[0] + " --decrease idx")


def main():
    verbose = 0
    op = ""
    ext = None
    try:
        opts, args = getopt.getopt(
                sys.argv[1:], 
                'hv', ['drop=', 'decrease=']
                )
    except getopt.GetoptError, err:
        print str(err)
        usage()

    for o, a in opts:
        if o in ('--help'):
            usage()
            exit(0)
        elif o in ('--decrease'):
            op = o
            ext = a
        else:
            assert False, 'oops, unhandled option: %s, -h for help' % o
            exit(1)

    config = Config()
    instencedrop = InstenceDrop(config, ext)

    if (o == '--decrease'):
        instencedrop.decrease()
    else:
        assert False, 'oops, unhandled option: %s, -h for help' % o
        exit(1)

        
if __name__ == '__main__':
    if (len(sys.argv) == 1):
        usage()
    else:
        main()
